package com.ttg.web.service.Impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.handler.inter.IWriter;
import com.ttg.common.constant.BasicConstant;
import com.ttg.common.entities.BasePage;
import com.ttg.common.entities.PagesRes;
import com.ttg.common.entities.UserTokenInfo;
import com.ttg.common.enums.*;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.JsonUtils;
import com.ttg.common.utils.ListBeanUtil;
import com.ttg.common.utils.UserUtil;
import com.ttg.common.utils.eazypoi.ExcelReportConfig;
import com.ttg.model.dto.*;
import com.ttg.model.po.QualityManageLadderRulePO;
import com.ttg.model.po.QualityManageTypeRulePO;
import com.ttg.model.pojo.*;
import com.ttg.model.vo.*;
import com.ttg.web.dao.*;
import com.ttg.web.service.QualityManageService;
import com.ttg.web.service.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Description： 质量管理service类
 * Author: chenyou
 * Date: 2025/8/18 15:39
 * Company: ttg
 * Copyright: Copyright (c) 2025
 */
@Slf4j
@Service
public class QualityManageServiceImpl implements QualityManageService {

    @Autowired
    private QualityManageRuleListDao qualityManageRuleListDao;
    @Autowired
    private QualityManageWeightConfigDao weightConfigDao;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private AdminLogDao adminLogDao;
    @Autowired
    private QualityManageLadderRuleDao ladderRuleDao;
    @Autowired
    private QualityManageTypeRuleDao typeRuleDao;
    @Autowired
    private QualityManageIndustryReportDao industryReportDao;
    @Autowired
    private QualityManageMerchReportDao merchReportDao;

    private static final Integer PAGE_SIZE = 1000;

    @Override
    public List<QualityManageRuleListVO> rulelist(QualityManageRuleListDTO reqDto) {
        return qualityManageRuleListDao.getByDimType(reqDto.getRuleDimType());
    }

    @Override
    public QMWeightConfigVO weightConfigShow(QMWeightConfigShowDTO reqDto) {
        QMWeightConfigVO vo = new QMWeightConfigVO();
        //参数检查
        dimTypeCheck(reqDto.getWcDimType());

        //获取用户信息
        UserTokenInfo user = UserUtil.getUserThrow();
        QualityManageWeightConfig weightConfig = weightConfigDao.getByUnique(user.getOrgNo(),reqDto.getWcDimType());
        if(Objects.isNull(weightConfig)){
            return vo;
        }
        BeanUtils.copyProperties(weightConfig,vo);
        return vo;
    }

    @Override
    public void weightConfigEditSave(QMWeightConfigSaveDTO reqDto) {
        UserTokenInfo user = UserUtil.getUserThrow();
        BigDecimal zero = BigDecimal.ZERO;
        if(Objects.isNull(reqDto.getWcDimType())){
            throw new BaseException(ErrorCodeEnums.QM_DIM_NOT_NULL);
        }
        if(DimTypeEnum.getByVal(reqDto.getWcDimType())==null){
            throw new BaseException(ErrorCodeEnums.QM_DIM_VAL_ERROR);
        }

        if(reqDto.getWcLivenessWeight()==null || reqDto.getWcLivenessWeight().compareTo(zero)<0){
            throw new BaseException(ErrorCodeEnums.QM_DIM_LIVENESS_WEIGHT_NOT_NULL);
        }
        if(reqDto.getWcClearCostWeight()==null || reqDto.getWcClearCostWeight().compareTo(zero)<0){
            throw new BaseException(ErrorCodeEnums.QM_DIM_CLEAR_COST_WEIGHT_NULL);
        }
        if(reqDto.getWcAvgWeight()==null || reqDto.getWcAvgWeight().compareTo(zero)<0){
            throw new BaseException(ErrorCodeEnums.QM_DIM_AVG_WEIGHT_NULL);
        }
        if(!(new BigDecimal(100).compareTo(reqDto.getWcLivenessWeight().add(reqDto.getWcClearCostWeight()).add(reqDto.getWcAvgWeight()))==0)){
            throw new BaseException(ErrorCodeEnums.QM_DIM_WEIGHT_SUM_VAL_ERROR);
        }

        QualityManageWeightConfig config = new QualityManageWeightConfig();
        BeanUtils.copyProperties(reqDto,config);

        config.setWcOrgNo(user.getOrgNo());
        config.setWcUpdateUser(user.getAdmId().toString());
        config.setWcUpdateTime(LocalDateTime.now());
        QualityManageWeightConfig old = weightConfigDao.getByUnique(user.getOrgNo(),reqDto.getWcDimType());
        if(old!=null){
            config.setWcId(old.getWcId());
            weightConfigDao.updateById(config);
        }else {
            weightConfigDao.save(config);
        }
        //更新配置list编辑时间
        QualityManageRuleList ruleList = qualityManageRuleListDao.getParam(reqDto.getWcDimType(),1);
        ruleList.setUpdateTime(LocalDateTime.now());
        qualityManageRuleListDao.updateById(ruleList);

        adminLogDao.addLog(user.getAdmId(), 1L, "u", user.getAdmId(), "行业/商户质量维度权重配置-编辑保存(" + JsonUtils.objectToJson(reqDto) + ")", user.getIp());
    }

    @Override
    public QMLadderRuleVO ladderRuleShow(QMLadderRuleShowDTO reqDto) {
        QMLadderRuleVO vo = new QMLadderRuleVO();
        UserTokenInfo user = UserUtil.getUserThrow();
        QualityManageLadderRulePO po = new QualityManageLadderRulePO();
        //参数检查
        dimTypeCheck(reqDto.getRuleDimType());
        ladderTypeCheck(reqDto.getRuleType());

        po.setRuleDimType(reqDto.getRuleDimType());
        po.setRuleType(reqDto.getRuleType());
        po.setRuleOrgNo(user.getOrgNo());
        po.setRuleAgentNo(user.getAgentNo());
        List<QualityManageLadderRule> list = ladderRuleDao.getByParam(po);
        List<QMLadderRuleDetailVO> vos = ListBeanUtil.copyListProperties(list, QMLadderRuleDetailVO::new);
        vo.setList(vos);
        SysConfig sysconfig = sysConfigService.getSysConfig("ladder_rule_type_" + reqDto.getRuleType());
        vo.setOrderBy(sysconfig.getSysValue());
        return vo;
    }

    @Override
    public void ladderRuleEditSave(QMLadderRuleSaveDTO reqDto) {
        UserTokenInfo user = UserUtil.getUserThrow();
        List<QMLadderRuleDTO> ladderRules = reqDto.getList();
        //参数检查
        if(Objects.isNull(reqDto.getRuleDimType())){
            throw new BaseException(ErrorCodeEnums.QM_DIM_NOT_NULL);
        }
        if(DimTypeEnum.getByVal(reqDto.getRuleDimType())==null){
            throw new BaseException(ErrorCodeEnums.QM_DIM_VAL_ERROR);
        }
        if(Objects.isNull(reqDto.getRuleType())){
            throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_NOT_NULL);
        }
        if(LadderRuleTypeEnum.getByVal(reqDto.getRuleType())==null){
            throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_TYPE_ERROR);
        }
        if(CollectionUtils.isEmpty(ladderRules)){
            throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_DATA_NOT_NULL);
        }
        for(QMLadderRuleDTO ladderRule : ladderRules){
            if(ladderRule.getRuleUpperBound()==null
                    || ladderRule.getRuleLowerBound()==null
                    || ladderRule.getRuleScore()==null ||
                    ladderRule.getRuleOrderId()==null){
                throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_DATA_NOT_NULL);
            }
        }
        //验证阶段数据连续性
        boolean check = validateladderRules(ladderRules, reqDto.getRuleType());
        if(!check){
            throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_DATA_ERROR);
        }

        List<QualityManageLadderRule> savelist = new ArrayList<>();
        for(QMLadderRuleDTO ladderRule : ladderRules){
            QualityManageLadderRule rule = new QualityManageLadderRule();
            rule.setRuleDimType(reqDto.getRuleDimType());
            rule.setRuleType(reqDto.getRuleType());
            rule.setRuleUpperBound(ladderRule.getRuleUpperBound());
            rule.setRuleLowerBound(ladderRule.getRuleLowerBound());
            rule.setRuleScore(ladderRule.getRuleScore());
            rule.setRuleOrderId(ladderRule.getRuleOrderId());
            rule.setRuleOrgNo(user.getOrgNo());
            rule.setRuleAgentNo(user.getAgentNo());
            rule.setRuleUpdateUser(user.getAdmId().toString());
            rule.setRuleUpdateTime(LocalDateTime.now());
            savelist.add(rule);
        }
        //更新配置list编辑时间
        RuleLIstEnum ruleLIstEnum = RuleLIstEnum.getByType(reqDto.getRuleDimType(), reqDto.getRuleType());
        QualityManageRuleList ruleList = qualityManageRuleListDao.getParam(ruleLIstEnum.getDimType(),ruleLIstEnum.getOrderId());
        ruleList.setUpdateTime(LocalDateTime.now());
        qualityManageRuleListDao.updateById(ruleList);
        //保存
        ladderRuleDao.saveOrUpdateBatch(savelist,reqDto.getRuleDimType(), reqDto.getRuleType());
        adminLogDao.addLog(user.getAdmId(), 1L, "u", user.getAdmId(), "行业/商户阶梯评价规则-编辑保存(" + JsonUtils.objectToJson(reqDto) + ")", user.getIp());
    }

    @Override
    public List<SymbolVO> symbol() {
        List<SymbolEnum> enums = Arrays.asList(SymbolEnum.values());
        return enums.stream().map(o -> {
            SymbolVO vo = new SymbolVO();
            vo.setValue(o.getValue());
            vo.setDesc(o.getDesc());
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<QMTypeRuleVO> typeRuleShow(QMTypeRuleShowDTO reqDto) {
        UserTokenInfo user = UserUtil.getUserThrow();
        //参数检查
        dimTypeCheck(reqDto.getDimType());

        QualityManageTypeRulePO po = new QualityManageTypeRulePO();
        po.setQtrDimType(reqDto.getDimType());
        po.setQtrOrgNo(user.getOrgNo());
        List<QualityManageTypeRule> list = typeRuleDao.getByParam(po);
        List<QMTypeRuleVO> vos = ListBeanUtil.copyListProperties(list, QMTypeRuleVO::new);
        return vos;
    }

    @Override
    public void typeRuleEditSave(QMTypeRuleSaveDTO reqDto) {
        UserTokenInfo user = UserUtil.getUserThrow();
        //参数检查
        dimTypeCheck(reqDto.getDimType());
        validateTypeRules(reqDto.getList());

        List<TypeRuleDTO> typeRuleList = reqDto.getList();
        List<QualityManageTypeRule> rules = ListBeanUtil.copyListProperties(typeRuleList,QualityManageTypeRule::new);
        for(QualityManageTypeRule rule:rules){
            rule.setQtrDimType(reqDto.getDimType());
            rule.setQtrOrgNo(user.getOrgNo());
            rule.setQtrAgentNo(user.getAgentNo());
            rule.setQtrUpdateUser(user.getAdmId().toString());
            rule.setQtrUpdateTime(LocalDateTime.now());
        }

        //更新配置list编辑时间
        QualityManageRuleList ruleList = qualityManageRuleListDao.getParam(reqDto.getDimType(),5);
        ruleList.setUpdateTime(LocalDateTime.now());
        qualityManageRuleListDao.updateById(ruleList);

        //按质量类别+二级类别 正序排
        Collections.sort(rules,Comparator.comparing(QualityManageTypeRule::getQtrType).thenComparing(QualityManageTypeRule::getQtrSubType));
//        //检查是否连续
//        boolean check= validateladderRules(rules);
//        if(!check){
//            throw new BaseException(ErrorCodeEnums.QM_TYPE_RULE_DATA_ERROR);
//        }
        typeRuleDao.saveOrUpdateBatch(rules,reqDto.getDimType());
        adminLogDao.addLog(user.getAdmId(), 1L, "u", user.getAdmId(), "行业/商户质量分类规则-编辑保存(" + JsonUtils.objectToJson(reqDto) + ")", user.getIp());
    }

    @Override
    public List<String> reportSelectYears(QMReportYearMonthDTO reqDto) {
        if(DimTypeEnum.商户维度.getValue() == reqDto.getDimType()){
            return merchReportDao.selectYears();
        }else if(DimTypeEnum.行业维度.getValue() == reqDto.getDimType()){
            return industryReportDao.selectYears();
        }else{
            throw new BaseException(ErrorCodeEnums.QM_DIM_VAL_ERROR);
        }
    }

    @Override
    public List<String> reportSelectMonths(QMReportYearMonthDTO reqDto) {
        if(StringUtils.isBlank(reqDto.getYear())){
            throw new BaseException("年份不能为空");
        }
        if(DimTypeEnum.商户维度.getValue() == reqDto.getDimType()){
            return merchReportDao.selectMonths(reqDto.getYear());
        }else if(DimTypeEnum.行业维度.getValue() == reqDto.getDimType()){
            return industryReportDao.selectMonths(reqDto.getYear());
        }else{
            throw new BaseException(ErrorCodeEnums.QM_DIM_VAL_ERROR);
        }
    }

    @Override
    public BasePage<QMIndustryReportVO> industryReport(QMReportDTO reqDto) {
        //参数检查
        dimTypeCheck(reqDto.getDimType());
        if(StringUtils.isBlank(reqDto.getYear())||StringUtils.isBlank(reqDto.getMonth())){
            throw new BaseException("请选择月份");
        }
        BasePage<QMIndustryReportVO> page = reqDto.parse();
        BasePage<QMIndustryReportVO> voPage = industryReportDao.report(page,reqDto);
        return voPage;
    }

    @Override
    public void industryReportDownload(QMReportDTO reqDto, HttpServletResponse response) {
        //选中指定一级二级行业下载对应范围商户数的明细文件
        //参数：只需要一级二级行业
        if(StringUtils.isBlank(reqDto.getClsId1())||StringUtils.isBlank(reqDto.getClsId2())){
            throw new BaseException("请选择一级二级行业分类");
        }
        if(StringUtils.isBlank(reqDto.getYear())||StringUtils.isBlank(reqDto.getMonth())){
            throw new BaseException("请选择月份");
        }
        reqDto.setDimType(DimTypeEnum.商户维度.getValue());

        //设置文件名称等参数
        ExcelReportConfig config = new ExcelReportConfig("行业商户质量报告报表", "industry_merch_report_export_");
        ExportParams exportParams = config.setExportParams();
        //设置表头
        List<ExcelExportEntity> entityList = new ArrayList<>();
        // 序号列
        ExcelExportEntity serialNumber = new ExcelExportEntity("序号", "serialNumber");
        serialNumber.setWrap(true);
        entityList.add(serialNumber);
        // 行业列（包含主分类、二级分类）
        ExcelExportEntity industryEntity = new ExcelExportEntity("行业分类", "industry");
        industryEntity.setWrap(true);
        List<ExcelExportEntity> industryList = new ArrayList<>();
        industryList.add(new ExcelExportEntity("主分类", "mainCategory"));
        industryList.add(new ExcelExportEntity("二级分类", "subCategory"));
        industryEntity.setList(industryList);
        entityList.add(industryEntity);
        // 商户信息
        ExcelExportEntity merchantEntity = new ExcelExportEntity("商户情况", "merchantInfo");
        merchantEntity.setWrap(true);
        List<ExcelExportEntity> merchantList = new ArrayList<>();
        merchantList.add(new ExcelExportEntity("商户编码", "mctNo"));
        merchantList.add(new ExcelExportEntity("商户名称", "mctName"));
        merchantList.add(new ExcelExportEntity("客户号", "custNo"));
        merchantEntity.setList(merchantList);
        entityList.add(merchantEntity);
        // 商户质量情况
        ExcelExportEntity qualityEntity = new ExcelExportEntity("商户质量情况", "qualityInfo");
        qualityEntity.setWrap(true);
        List<ExcelExportEntity> qualityList = new ArrayList<>();
        qualityList.add(new ExcelExportEntity("活跃天数", "livenessDay"));
        qualityList.add(new ExcelExportEntity("清算成本", "clearCost"));
        qualityList.add(new ExcelExportEntity("日均存款", "avg"));
        qualityEntity.setList(qualityList);
        entityList.add(qualityEntity);

        //报表数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        IWriter<Workbook> workbookIWriter = ExcelExportUtil.exportBigExcel(exportParams, entityList);
        reqDto.setPageSize(PAGE_SIZE);
        int extCount = 0;
        int total = 0;
        // 每次1000条，1000次就有100万，如果超过100w，xlsx也导不出来了，需要换方式，所以这里循环最多1000
        for (int i = 1; i <= 1000; i++) {
            reqDto.setPage(i);
            BasePage<QMMerchReportVO> index = merchReport(reqDto);
            PagesRes pagesRes = index.getPagesRes();
            total = (int) pagesRes.getTotalnum();
            extCount += CollectionUtils.isEmpty(index.getList()) ? 0 : index.getList().size();
            dataList.addAll(bulidIndustryDataList(index.getList()));
            workbookIWriter.write(dataList);
            dataList.clear();
            if (extCount >= total) {
                break;
            }
        }
        this.workbookExport(workbookIWriter, response, config.getTitle(), config.getFileType());
    }

    @Override
    public BasePage<QMMerchReportVO> merchReport(QMReportDTO reqDto) {
        //参数检查
        dimTypeCheck(reqDto.getDimType());
        if(StringUtils.isBlank(reqDto.getYear())||StringUtils.isBlank(reqDto.getMonth())){
            throw new BaseException("请选择月份");
        }
        BasePage<QMMerchReportVO> page = reqDto.parse();
        BasePage<QMMerchReportVO> voPage = merchReportDao.report(page,reqDto);
        return voPage;
    }

    @Override
    public void merchReportDownload(QMReportDTO reqDto, HttpServletResponse response) {
        if(StringUtils.isBlank(reqDto.getYear())||StringUtils.isBlank(reqDto.getMonth())){
            throw new BaseException("请选择月份");
        }
        reqDto.setDimType(DimTypeEnum.商户维度.getValue());
        //设置文件名称等参数
        ExcelReportConfig config = new ExcelReportConfig("商户质量报告报表", "merch_report_export_");
        ExportParams exportParams = config.setExportParams();
        //设置表头
        List<ExcelExportEntity> entityList = new ArrayList<>();
        // 序号列
        ExcelExportEntity serialNumber = new ExcelExportEntity("序号", "serialNumber");
        serialNumber.setWrap(true);
        entityList.add(serialNumber);

        // 商户情况
        ExcelExportEntity merchantEntity = new ExcelExportEntity("商户情况", "merchantInfo");
        merchantEntity.setWrap(true);
        List<ExcelExportEntity> merchantList = new ArrayList<>();
        merchantList.add(new ExcelExportEntity("商户编码", "mctNo"));
        merchantList.add(new ExcelExportEntity("商户名称", "mctName"));
        merchantList.add(new ExcelExportEntity("客户号", "custNo"));
        merchantEntity.setList(merchantList);
        entityList.add(merchantEntity);

        // 行业列（包含主分类、二级分类）
        ExcelExportEntity industryEntity = new ExcelExportEntity("行业分类", "industry");
        industryEntity.setWrap(true);
        List<ExcelExportEntity> industryList = new ArrayList<>();
        industryList.add(new ExcelExportEntity("主分类", "mainCategory"));
        industryList.add(new ExcelExportEntity("二级分类", "subCategory"));
        industryEntity.setList(industryList);
        entityList.add(industryEntity);

        // 商户质量情况
        ExcelExportEntity qualityEntity = new ExcelExportEntity("商户质量情况（单位：天/%/万元）", "qualityInfo");
        qualityEntity.setWrap(true);
        List<ExcelExportEntity> qualityList = new ArrayList<>();
        qualityList.add(new ExcelExportEntity("活跃天数", "livenessDay"));
        qualityList.add(new ExcelExportEntity("年清算成本（年补贴/ 年日均）", "clearCost"));
        qualityList.add(new ExcelExportEntity("户均归集（年日均）", "avg"));
        qualityEntity.setList(qualityList);
        entityList.add(qualityEntity);

        // 商户评价得分情况
        ExcelExportEntity qualityScoreEntity = new ExcelExportEntity("商户质量情况（单位：天/%/万元）", "qualityScore");
        qualityScoreEntity.setWrap(true);
        List<ExcelExportEntity> qualityScoreList = new ArrayList<>();
        qualityScoreList.add(new ExcelExportEntity("活跃得分", "livenessScore"));
        qualityScoreList.add(new ExcelExportEntity("清算成本得分", "clearCostScore"));
        qualityScoreList.add(new ExcelExportEntity("存款归集得分", "avgScore"));
        qualityScoreList.add(new ExcelExportEntity("加权得分", "weightScore"));
        qualityScoreEntity.setList(qualityScoreList);
        entityList.add(qualityScoreEntity);

        // 指导分类
        ExcelExportEntity qualityType = new ExcelExportEntity("指导分类", "qualityType");
        qualityType.setWrap(true);
        entityList.add(qualityType);

        //报表数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        IWriter<Workbook> workbookIWriter = ExcelExportUtil.exportBigExcel(exportParams, entityList);
        reqDto.setPageSize(PAGE_SIZE);
        int extCount = 0;
        int total = 0;
        // 每次1000条，1000次就有100万，如果超过100w，xlsx也导不出来了，需要换方式，所以这里循环最多1000
        for (int i = 1; i <= 1000; i++) {
            reqDto.setPage(i);
            BasePage<QMMerchReportVO> index = merchReport(reqDto);
            PagesRes pagesRes = index.getPagesRes();
            total = (int) pagesRes.getTotalnum();
            extCount += CollectionUtils.isEmpty(index.getList()) ? 0 : index.getList().size();
            dataList.addAll(bulidMerchDataList(index.getList()));
            workbookIWriter.write(dataList);
            dataList.clear();
            if (extCount >= total) {
                break;
            }
        }
        this.workbookExport(workbookIWriter, response, config.getTitle(), config.getFileType());
    }

    public List<Map<String, Object>> bulidIndustryDataList(List<QMMerchReportVO> resultList){
        List<Map<String, Object>> partDataList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(resultList)) {
            for(int i = 0; i < resultList.size(); i++){
                QMMerchReportVO vo = resultList.get(i);
                Map<String, Object> data = new HashMap<>();
                data.put("serialNumber", i + 1);

                // 行业分类 - 需要嵌套结构
                List<Map<String, Object>> industryList = new ArrayList<>();
                Map<String, Object> industryMap = new HashMap<>();
                industryMap.put("mainCategory", vo.getRepClsName1());
                industryMap.put("subCategory", vo.getRepClsName2());
                industryList.add(industryMap);
                data.put("industry",industryList);

                // 商户情况 - 需要嵌套结构
                List<Map<String, Object>> merchantList = new ArrayList<>();
                Map<String, Object> merchantMap = new HashMap<>();
                merchantMap.put("mctNo", vo.getRepMctNo());
                merchantMap.put("mctName", vo.getRepMctName());
                merchantMap.put("custNo", vo.getRepMctCustNo());
                merchantList.add(merchantMap);
                data.put("merchantInfo",merchantList);

                // 商户质量情况 - 需要嵌套结构
                List<Map<String, Object>> qualityList = new ArrayList<>();
                Map<String, Object> qualityMap = new HashMap<>();
                qualityMap.put("livenessDay", vo.getRepLivenessDay());
                qualityMap.put("clearCost", vo.getRepClearCost());
                qualityMap.put("avg", vo.getRepAvg());
                qualityList.add(qualityMap);
                data.put("qualityInfo",qualityList);
                partDataList.add(data);
            }
        }
        return partDataList;
    }

    public List<Map<String, Object>> bulidMerchDataList(List<QMMerchReportVO> resultList){
        List<Map<String, Object>> partDataList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(resultList)) {
            for(int i = 0; i < resultList.size(); i++){
                QMMerchReportVO vo = resultList.get(i);
                Map<String, Object> data = new HashMap<>();
                data.put("serialNumber", i + 1);

                // 商户情况 - 需要嵌套结构
                List<Map<String, Object>> merchantList = new ArrayList<>();
                Map<String, Object> merchantMap = new HashMap<>();
                merchantMap.put("mctNo", vo.getRepMctNo());
                merchantMap.put("mctName", vo.getRepMctName());
                merchantMap.put("custNo", vo.getRepMctCustNo());
                merchantList.add(merchantMap);
                data.put("merchantInfo",merchantList);

                // 行业分类 - 需要嵌套结构
                List<Map<String, Object>> industryList = new ArrayList<>();
                Map<String, Object> industryMap = new HashMap<>();
                industryMap.put("mainCategory", vo.getRepClsName1());
                industryMap.put("subCategory", vo.getRepClsName2());
                industryList.add(industryMap);
                data.put("industry",industryList);

                // 商户质量情况 - 需要嵌套结构
                List<Map<String, Object>> qualityList = new ArrayList<>();
                Map<String, Object> qualityMap = new HashMap<>();
                qualityMap.put("livenessDay", vo.getRepLivenessDay());
                qualityMap.put("clearCost", vo.getRepClearCost());
                qualityMap.put("avg", vo.getRepAvg());
                qualityList.add(qualityMap);
                data.put("qualityInfo",qualityList);
                partDataList.add(data);

                // 商户评价得分情况 - 需要嵌套结构
                List<Map<String, Object>> qualityScoreList = new ArrayList<>();
                Map<String, Object> qualityScoreMap = new HashMap<>();
                qualityScoreMap.put("livenessScore", vo.getRepLivenessScore());
                qualityScoreMap.put("clearCostScore", vo.getRepClearCostScore());
                qualityScoreMap.put("avgScore", vo.getRepAvgScore());
                qualityScoreMap.put("weightScore", vo.getRepWeightScore());
                qualityScoreList.add(qualityScoreMap);
                data.put("qualityScore",qualityScoreList);
                partDataList.add(data);

                //指导分类
                data.put("qualityType", vo.getQtrTypeName());
            }
        }
        return partDataList;
    }

    /**
     * 验证阶梯数据的连续性
     * @param ladderRules 阶梯数据
     * @param ruleType 阶梯排序规则 asc正序，desc反序
     * @return: boolean
     * @date: 2025/8/26 16:26
     * @author: chenyou
     */
    public boolean validateladderRules(List<QMLadderRuleDTO> ladderRules,Integer ruleType) {
        SysConfig sysconfig = sysConfigService.getSysConfig("ladder_rule_type_" + ruleType);
        // 1. 根据组内序号重新排序
        ladderRules.sort(Comparator.comparing(QMLadderRuleDTO::getRuleOrderId));

        if(BasicConstant.ASC.equals(sysconfig.getSysValue())) {
            // 2. 遍历检查 (从第0个到倒数第二个)
            for (int i = 0; i < ladderRules.size() - 1; i++) {
                QMLadderRuleDTO currentStep = ladderRules.get(i);
                QMLadderRuleDTO nextStep = ladderRules.get(i + 1);
                //按从小到大划分阶梯规则,即值越小得分越高,连接点为上一阶的上限值=下一阶的下限值
                BigDecimal currentUpper = currentStep.getRuleUpperBound();
                BigDecimal nextLower = nextStep.getRuleLowerBound();

                // 关键比较：当前阶的上限必须等于下一阶的下限
                if (currentUpper == null && nextLower == null) {
                    // 两者都为null，通常不允许，视为不相等
                    return false;
                }
                // 一个为null，一个不为null，肯定不相等
                else if (currentUpper == null || nextLower == null) {
                    return false;
                }
                // 使用 compareTo 比较 BigDecimal，0 表示相等
                else if (currentUpper.compareTo(nextLower) != 0) {
                    return false;
                }
                // 如果相等，则继续循环
            }
        }

        if(BasicConstant.DESC.equals(sysconfig.getSysValue())) {
            // 2. 遍历检查 (从第0个到倒数第二个)
            for (int i = 0; i < ladderRules.size() - 1; i++) {
                QMLadderRuleDTO currentStep = ladderRules.get(i);
                QMLadderRuleDTO nextStep = ladderRules.get(i + 1);
                //按从大到小划分阶梯规则,即值越大得分越高,连接点为上一阶的下限值=下一阶的上限值
                BigDecimal currentUpper = currentStep.getRuleLowerBound();
                BigDecimal nextLower = nextStep.getRuleUpperBound();

                // 关键比较：当前阶的上限必须等于下一阶的下限
                if (currentUpper == null && nextLower == null) {
                    // 两者都为null，通常不允许，视为不相等
                    return false;
                }
                // 一个为null，一个不为null，肯定不相等
                else if (currentUpper == null || nextLower == null) {
                    return false;
                }
                // 使用 compareTo 比较 BigDecimal，0 表示相等
                else if (currentUpper.compareTo(nextLower) != 0) {
                    return false;
                }
                // 如果相等，则继续循环
            }
        }

        // 3. 如果循环顺利完成，所有连接点都检查通过
        return true;
    }

    /**
     * 验证行业/商户质量分类规则，一级分类连续性
     * @param rules 阶梯数据
     * @return: boolean
     * @date: 2025/8/26 16:26
     * @author: chenyou
     */
    public boolean validateladderRules(List<QualityManageTypeRule> rules) {
        // 1. 默认为倒序排
        // 2. 按一级分类去重
        List<QualityManageTypeRule> level1list = new ArrayList<>();
        for(QualityManageTypeRule rule:rules){
            if(level1list.size()==0){
                level1list.add(rule);
                continue;
            }
            boolean match = level1list.stream().anyMatch(o -> o.getQtrType().equals(rule.getQtrType()));
            if(!match){
                level1list.add(rule);
            }
        }
        // 3. 遍历检查一级分类连续性 (从第0个到倒数第二个)
        for (int i = 0; i < level1list.size() - 1; i++) {
            QualityManageTypeRule currentStep = level1list.get(i);
            QualityManageTypeRule nextStep = level1list.get(i + 1);
            //按从大到小划分阶梯规则,即值越大得分越高,连接点为上一阶的下限值=下一阶的上限值
            BigDecimal currentUpper = currentStep.getQtrLowerBound();
            BigDecimal nextLower = nextStep.getQtrUpperBound();

            // 关键比较：当前阶的上限必须等于下一阶的下限
            if (currentUpper == null && nextLower == null) {
                // 两者都为null，通常不允许，视为不相等
                return false;
            }
            // 一个为null，一个不为null，肯定不相等
            else if (currentUpper == null || nextLower == null) {
                return false;
            }
            // 使用 compareTo 比较 BigDecimal，0 表示相等
            else if (currentUpper.compareTo(nextLower) != 0) {
                return false;
            }
            // 如果相等，则继续循环
        }

        // 4. 如果循环顺利完成，所有连接点都检查通过
        return true;
    }
    public void dimTypeCheck(Integer dimType){
        if(Objects.nonNull(dimType)){
            if(DimTypeEnum.getByVal(dimType)==null){
                throw new BaseException(ErrorCodeEnums.QM_DIM_VAL_ERROR);
            };
        }
    }

    public void ladderTypeCheck(Integer ladderType){
        if(Objects.nonNull(ladderType)){
            if(LadderRuleTypeEnum.getByVal(ladderType)==null){
                throw new BaseException(ErrorCodeEnums.QM_LADDER_RULE_TYPE_ERROR);
            };
        }
    }

    public void validateTypeRules(List<TypeRuleDTO> typeRuleList){
        for(TypeRuleDTO dto:typeRuleList){
            if(QualityRuleTypeEnum.getByVal(dto.getQtrType(),dto.getQtrSubType()) == null){
                throw new BaseException(ErrorCodeEnums.QM_TYPE_RULE_ERROR);
            }
        }
    }

    public List<QMIndustryReportExportVO> industryConvert(List<QMMerchReportVO> index){
       return ListBeanUtil.copyListProperties(index,QMIndustryReportExportVO::new);
    }

    public List<QMMerchReportExportVO> merchConvert(List<QMMerchReportVO> index){
        return ListBeanUtil.copyListProperties(index,QMMerchReportExportVO::new);
    }

    public void workbookExport(IWriter<Workbook> workbookIWriter, HttpServletResponse response, String fileName, String fileType) {
        try (ServletOutputStream outputStream = response.getOutputStream(); Workbook workbook = workbookIWriter.get()) {
            if (workbook != null) {
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + fileType, "UTF-8"));
                response.setHeader("Access-Control-Expose-Headers", "filename");
                response.setHeader("filename", URLEncoder.encode(fileName + fileType, "UTF-8"));
                workbook.write(outputStream);
            }
        } catch (IOException e) {
            log.error("导出异常{}", fileName, e);
            throw new BaseException(ErrorCodeEnums.SYSTEM_ERROR.getErrcode(), "报表导出异常");
        }
    }
}
